/*
 * $Id: AddEditAOItem.java 28 2013-05-21 12:11:22Z antonyhands@gmail.com $
 */
package ru.olympus.antonyhands.ao.ui;

import java.util.ArrayList;
import java.util.List;

import ru.olympus.antonyhands.ao.UIHelper;
import ru.olympus.antonyhands.ao.data.AOData;
import ru.olympus.antonyhands.ao.data.entities.AOItem;
import ru.olympus.antonyhands.ao.data.entities.CraftInfo;
import ru.olympus.antonyhands.ao.data.entities.CraftSkill;
import ru.olympus.antonyhands.ao.data.entities.ItemCategory;
import ru.olympus.antonyhands.ao.data.entities.ItemQuantityPair;
import ru.olympus.antonyhands.ao.data.util.ByTitleComparator;
import ru.olympus.antonyhands.ao.ui.helper.ResourcesTableHelper;
import ru.olympus.antonyhands.ao.ui.listener.CancelButtonClickListener;
import ru.olympus.antonyhands.ao.util.GoogleIterable;
import ru.olympus.antonyhands.ao.util.StringUtilities;

import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

/**
 * Компонент добавления предмета
 * 
 * @author AntonyHands
 * @since 16.05.2013
 */
public class AddEditAOItem extends CustomComponent
{
    private static final long serialVersionUID = -9081408710828872659L;

    private AOItem _item;
    private Component _returnComponent;

    private VerticalLayout mainLayout;

    private Label _error = new Label();
    private TextField _code = new TextField("Код");
    private TextField _title = new TextField("Название");
    private ComboBox _category;
    private TextField _fixedPrice = new TextField("Фиксированная цена");
    private ComboBox _craftSkill;
    private VerticalLayout _craftLayout = new VerticalLayout();
    private TextField _craftLevel = new TextField("Уровень навыка");
    private TextField _workload = new TextField("Количество единиц труда");
    private TextField _createdElementsNumber = new TextField("Количество произведённых предметов");
    private Table _resources;
    private Button _addResourceButton = new Button("Ещё ресурс");
    private Button _addButton = new Button("Добавить");
    private Button _editButton = new Button("Редактировать");
    private Button _cancelButton = new Button("Отмена");
    
    private Integer nextResourceId = new Integer(0);

    public AddEditAOItem()
    {
        this(null, null);
    }

    public AddEditAOItem(AOItem item, Component returnComponent)
    {
        _item = item;
        _returnComponent = returnComponent;
        setCompositionRoot(buildMainLayout());
    }

    private Component buildMainLayout()
    {
        mainLayout = new VerticalLayout();

        mainLayout.addComponent(new Label(_item == null ? "Добавление предмета" : "Редактирование предмета"));
        
        mainLayout.addComponent(_error);
        
        mainLayout.addComponent(_code);
        if (_item != null)
            _code.setValue(_item.getCode());
        
        mainLayout.addComponent(_title);
        if (_item != null)
            _title.setValue(_item.getTitle());

        _category = new ComboBox("Категория");
        UIHelper.refillSelect(_category, AOData.getInstance().listItemCategories());
        _category.setTextInputAllowed(false);
        _category.setNullSelectionAllowed(false);
        mainLayout.addComponent(_category);
        if (_item != null)
            _category.setValue(_item.getItemCategory().getCode());

        mainLayout.addComponent(_fixedPrice);
        if (_item != null)
            _fixedPrice.setValue(StringUtilities.longToString(_item.getFixedPrice()));

        _craftSkill = new ComboBox("Навык производства");
        UIHelper.refillSelect(_craftSkill, AOData.getInstance().listCraftSkills());
        _craftSkill.setTextInputAllowed(false);
        _craftSkill.setNullSelectionAllowed(true);
        _craftSkill.setImmediate(true);
        _craftSkill.addListener(new ValueChangeListener()
        {
            private static final long serialVersionUID = 7405850360993184197L;

            @Override
            public void valueChange(ValueChangeEvent event)
            {
                if (event.getProperty().getValue() == null)
                    _craftLayout.setVisible(false);
                else
                    _craftLayout.setVisible(true);
            }
        });
        mainLayout.addComponent(_craftSkill);
        if (_item != null)
            _craftSkill.setValue(_item.getCraftInfo().getCraftSkill().getCode());

        addCraftLayout();
        _craftLayout.setVisible(_item != null && _item.getCraftInfo() != null);

        HorizontalLayout buttonsLayout = new HorizontalLayout();
        mainLayout.addComponent(buttonsLayout);

        _addButton.addListener(new AddButtonClickListener());
        _editButton.addListener(new EditButtonClickListener());
        if (_item == null)
            buttonsLayout.addComponent(_addButton);
        else
            buttonsLayout.addComponent(_editButton);

        _cancelButton.addListener(new CancelButtonClickListener());
        buttonsLayout.addComponent(_cancelButton);

        return mainLayout;
    }

    private void addCraftLayout()
    {
        mainLayout.addComponent(_craftLayout);

        _craftLayout.addComponent(_craftLevel);

        _craftLayout.addComponent(_workload);

        _craftLayout.addComponent(_createdElementsNumber);

        _resources = ResourcesTableHelper.createResourcesTable();
        _craftLayout.addComponent(_resources);

        if (_item != null)
        {
            _craftLevel.setValue(StringUtilities.longToString(_item.getCraftInfo().getCraftLevel()));
            _workload.setValue(StringUtilities.longToString(_item.getCraftInfo().getWorkload()));
            _createdElementsNumber.setValue(StringUtilities.longToString(_item.getCraftInfo().getResultItemData().getValue()));
            for (ItemQuantityPair resource : _item.getCraftInfo().listInputItemsData())
            {
                ResourcesTableHelper.addRowToResourcesTable(_resources, nextResourceId++, resource.getKey().getCode(), resource.getValue());
            }
        }

        _addResourceButton.addListener(new ClickListener()
        {
            private static final long serialVersionUID = 1797665365767614613L;

            @Override
            public void buttonClick(ClickEvent event)
            {
                ResourcesTableHelper.addRowToResourcesTable(_resources, nextResourceId++, null, new Long(1));
            }
        });
        _craftLayout.addComponent(_addResourceButton);
    }

    private void addRowToResourcesTable(String itemCode, Long quantity)
    {
        ComboBox itemBox = new ComboBox();
        itemBox.setNullSelectionAllowed(false);
        List<AOItem> list = GoogleIterable.with(AOData.getInstance().listItems())
                .sort(new ByTitleComparator()).toArrayList();
        UIHelper.refillSelect(itemBox, list);
        if (list.size() > 0)
            itemBox.setValue(StringUtilities.isEmpty(itemCode) ? list.get(0).getCode() : itemCode);
        Button delButton = new Button("Удалить");
        delButton.addListener(new ClickListener()
        {
            private static final long serialVersionUID = 6016282560688968264L;

            private final Integer resId = nextResourceId;

            @Override
            public void buttonClick(ClickEvent event)
            {
                _resources.removeItem(resId);
            }
        });
        _resources.addItem(new Object[]{ itemBox, quantity, delButton }, nextResourceId++);
    }

    private class AddButtonClickListener implements ClickListener
    {
        private static final long serialVersionUID = 2838241998056055070L;

        @Override
        public void buttonClick(ClickEvent event)
        {
            // проверки
            String code = (String)_code.getValue();
            if (StringUtilities.isEmpty(code))
            {
                _error.setValue("Поле '" + _code.getCaption() + "' не заполнено");
                return;
            }
            String title = (String)_title.getValue();
            if (StringUtilities.isEmpty(title))
            {
                _error.setValue("Поле '" + _title.getCaption() + "' не заполнено");
                return;
            }
            for (AOItem item : AOData.getInstance().listItems())
            {
                if (item.getCode().equals(code))
                {
                    _error.setValue("Элемент с кодом '" + code + "' уже существует");
                    return;
                }
                if (item.getTitle().equals(title))
                {
                    _error.setValue("Элемент с названием '" + title + "' уже существует");
                    return;
                }
            }
            // можно сохранять данные о предмете
            ItemCategory category = AOData.getInstance().getItemCategoryByCode((String)_category.getValue());
            if (category == null)
            {
                _error.setValue("Категория не выбрана");
                return;
            }
            AOItem item = new AOItem(code, title, category);
            item.setFixedPrice(StringUtilities.stringToLong((String)_fixedPrice.getValue()));

            AOData.getInstance().addItem(item);

            CraftSkill craftSkill = AOData.getInstance().getCraftSkillByCode((String)_craftSkill.getValue());
            if (craftSkill != null)
            {
                Long craftLevel = StringUtilities.stringToLong((String)_craftLevel.getValue());
                Long workload = StringUtilities.stringToLong((String)_workload.getValue());
                Long createdElementsNumber = StringUtilities.stringToLong((String)_createdElementsNumber.getValue());
                ItemQuantityPair result = new ItemQuantityPair(item, createdElementsNumber);
                List<ItemQuantityPair> inputItems = new ArrayList<ItemQuantityPair>();
                for (Object inputItemId : _resources.getItemIds())
                {
                    Item inputItem = _resources.getItem(inputItemId);
                    AOItem inputAOItem = AOData.getInstance().getItemByCode((String)
                            ((ComboBox)inputItem.getItemProperty("item").getValue()).getValue());
                    Long quantity = (Long)inputItem.getItemProperty("quantity").getValue();
                    inputItems.add(new ItemQuantityPair(inputAOItem, quantity));
                }
                CraftInfo ci = new CraftInfo(craftSkill, craftLevel, workload, result, inputItems);
                AOData.getInstance().addItemExchangeBase(ci);
            }
            UIHelper.clearScreen();
        }
    }

    private class EditButtonClickListener implements ClickListener
    {
        private static final long serialVersionUID = 2932880308990548914L;

        @Override
        public void buttonClick(ClickEvent event)
        {
            // проверки
            String code = (String)_code.getValue();
            if (StringUtilities.isEmpty(code))
            {
                _error.setValue("Поле '" + _code.getCaption() + "' не заполнено");
                return;
            }
            String title = (String)_title.getValue();
            if (StringUtilities.isEmpty(title))
            {
                _error.setValue("Поле '" + _title.getCaption() + "' не заполнено");
                return;
            }
            ItemCategory category = AOData.getInstance().getItemCategoryByCode((String)_category.getValue());
            if (category == null)
            {
                _error.setValue("Категория не выбрана");
                return;
            }
            // можно сохранять данные о предмете
            _item.setTitle(title);
            _item.setCode(code);
            _item.setFixedPrice(StringUtilities.stringToLong((String)_fixedPrice.getValue()));

            // сначала просто снесём крафтовую инфу
            AOData.getInstance().removeItemExchangeBase(_item.getCraftInfo());

            CraftSkill craftSkill = AOData.getInstance().getCraftSkillByCode((String)_craftSkill.getValue());
            if (craftSkill != null)
            {
                Long craftLevel = StringUtilities.stringToLong((String)_craftLevel.getValue());
                Long workload = StringUtilities.stringToLong((String)_workload.getValue());
                Long createdElementsNumber = StringUtilities.stringToLong((String)_createdElementsNumber.getValue());
                ItemQuantityPair result = new ItemQuantityPair(_item, createdElementsNumber);
                List<ItemQuantityPair> inputItems = new ArrayList<ItemQuantityPair>();
                for (Object inputItemId : _resources.getItemIds())
                {
                    Item inputItem = _resources.getItem(inputItemId);
                    AOItem inputAOItem = AOData.getInstance().getItemByCode((String)
                            ((ComboBox)inputItem.getItemProperty("item").getValue()).getValue());
                    Long quantity = (Long)inputItem.getItemProperty("quantity").getValue();
                    inputItems.add(new ItemQuantityPair(inputAOItem, quantity));
                }
                CraftInfo ci = new CraftInfo(craftSkill, craftLevel, workload, result, inputItems);
                AOData.getInstance().addItemExchangeBase(ci);
            }
            UIHelper.changeCurrentComponent(_returnComponent);
        }
    }
}
